PICTScavenger
Volume Number: 7
Issue Number: 3
Column Tag: Pascal Procedures
Picture Resource Scavenger
By David T. Craig, Kansas CIty, MO
INTRODUCTION
This article describes a MPW Pascal 3.0 unit that scavenges QuickDraw picture
resources from corrupted resource files.
This unit produces as output a standard Macintosh text file containing the source
listing for all the scavenged picture resources in a format compatible with Apple’s Rez
tool along with the actual scavenged picture resources which may be viewed by a
program like Apple’s ResEdit.
All non-corrupted picture resources (type ‘PICT’) within a file will be found by
this program. This program makes no assumptions about the resource file. As such,
this program ignores any format that the resource may contain. For example, the
Resource Header is not assumed to be intact and is not used.
Progress information may also be displayed by this unit during the scavenging
process. Currently, this information consists of simple phrases which detail the
scavenger’s progress on a picture basis. This information is only displayed if the
program that uses this unit is running under the Apple MPW Shell. If the MPW Shell is
not active, then no progress information appears.
A file containing PICT resources may become corrupted in many ways. Once
corrupted, a file’s resources can not be accessed. If Apple’s ResEdit program can not
open a file, then you are seriously in need of this PICT scavenger. Most resource files
which become corrupt generally have an invalid Resource Header and Resource Map.
These two areas within a resource file point to the actual resource data.
This unit should be viewed from a global Macintosh perspective as a first step in
providing a set of modules that reconstruct corrupted data from Macintosh files. This
concept is not new and has been around, as I far as I know, since the Xerox Alto in the
mid 1970’s. In this author’s opinion, these types of services should exist at two levels.
The first level is the lowest level and involves device data integrity. This means disk
drives. Apple Computer should provide this level of service via its Macintosh
Operating System. If a file becomes corrupted the OS should detect this fact, inform the
user, and attempt to regain the corrupted data. Apple in its wonderful Lisa computer
provided such a feature via the Lisa Scavenger and Tag Bytes on disk media. Apple has
not pursued this avenue with the Macintosh. See Apple Macintosh Technical Note # 94
for Tag Byte information. The second level of data integrity involves the integrity of
file contents. This level of service can only be provided by the authors of Macintosh
applications and their related documents. Implementing this service would require
checksums (which includes CRCs), redundant file data structures, and built-in
application recovery methods.
USING THIS UNIT
This unit contains two public routines. Routine PICT_Unit_Version returns a
string representing the version number and compilation date and time of this unit.
Routine PICT_Scavenger performs the actual scavenging process. The Pascal interface
for this routine follows:
{1}
{ •••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
• Routine ..... PICT_Scavenger
• Purpose ..... Scavenge all the picture (PICT) resources
• found in a file and write the picture data to a text file
• containing the picture data as PICT resources and Rez
• source code
• Input .. ps_program_name - name of program (for text file)
• ps_input_file_name - corrupted input file to scavenge
• ps_input_file_volume - input file volume reference
• ps_output_file_name - text output file for Rez source
• ps_output_file_volume - output file volume reference
• ps_show_progress - show scavenging progress flag
• ps_pict_header_info - picture header/tail info
• ps_starting_id - picture resource starting ID value
• ps_decrement_id - decrement resource ID flag
• Output ..ps_num_found_picts - no. pictures found in input file
• ps_num_pict_failures - no. picture scavenge failures
• ps_error - error result
••••••••••••••••••••••••••••••••••••••••••••••••••••••••• }
PROCEDURE PICT_Scavenger ( ps_program_name: Str255;
ps_input_file_name : Str255;
ps_input_file_volume : INTEGER;
ps_output_file_name : Str255;
ps_output_file_volume : INTEGER;
ps_show_progress : BOOLEAN;
ps_pict_header_info : PS_t_PHI_List;
ps_starting_id : INTEGER;
ps_decrement_id : BOOLEAN;
VAR ps_num_found_picts : INTEGER;
VAR ps_num_pict_failures : INTEGER;
VAR ps_error : INTEGER);
The key to this routine is the data type PS_t_PHI_List. This type contains a list
of patterns which the unit uses to search for a PICT resource in a resource file. The
type has the following structure:
{2}
PS_t_PHI_List = ARRAY [1..PS_c_MaxPICTVersions{4}] OF
PS_t_PICT_Header_Info;
where PS_t_PICT_Header_Info has the structure:
{3}
PS_t_PICT_Header_Info = RECORD
hi_version_data : Ptr; { header info }
hi_version_data_length : INTEGER;
hi_endpict_data : Ptr;
hi_endpict_data_length : INTEGER; { footer info }
END;
To scavenge version 1 pictures use the following values:
hi_version_data points to buffer holding value $1101
hi_version_data_length = 2
hi_endpict_data points to buffer holding $FF
hi_endpict_data_length = 1
To scavenge version 2 pictures use the following values:
hi_version_data points to buffer holding value $001102FF
hi_version_data_length = 4
hi_endpict_data points to buffer holding $00FF
hi_endpict_data_length = 2
Note that up to 4 picture header patterns may be used, but currently only two
are needed since only two picture versions exist.
I wrote a simple MPW Shell tool called PICTScavenger in MPW Pascal 3.0 which
tests this unit and provides a nice programming framework for tools. This tool has the
following command line:
# 4
PICTScavenger [-p] [-s start_id] [-d] input_file [output_file]
The arguments are as follows:
-p: Show progress information. The default is to NOT show any progress
information.
-s: Set starting PICT resource ID value to start_id. The default value is 1000.
-d: Decrement resource ID. The default is to increment the ID value.
Argument input_file is the name of the corrupted file. This argument must
always exist in the argument list. This name MUST occur before the name of the output
file, if one exists. Argument output_file is the name of the output file which will
contain a Rez-compatible source listing of the pictures found in the corrupted input
file. If no output file is specified, then a default output file is created whose name
consists of the input file name suffixed with “.PICT.r”.
When run using a test file named “test” as input the following information
appears in a MPW window:
PictScavenger -p test
Macintosh PICT File Scavenger 1.0.0 [9/28/90 - 11:06:12 AM]
David T. Craig (736 Edgewater, Wichita, Kansas 67230)
Not Copyright (c) 1990
PICT Scavenger unit version: 1.1.0 [9/28/90 - 3:25:23 PM]
Scavenging file “test” to Rez file “test.PICT.r” ...
Searching for PICT HEAD $1101 and PICT TAIL $FF
Scavenging PICT # 1000 [Address $00010E Length $0001D5]
Scavenging PICT # 1001 [Address $0002E7 Length $000677]
Scavenging PICT # 1002 [Address $000962 Length $000089]
*** PICT scavenge failure [Address $001800]
Searching for PICT HEAD $001102FF and PICT TAIL $00FF
Scavenging PICT # 1003 [Address $0009EF Length $0007A0]
Scavenging PICT # 1004 [Address $001193 Length $000716]
PICT Scavenger Summary:
Input file : test
Output file : test.PICT.r
Scavenged PICTs : 5
Scavenge failures : 1
Elapsed time : 0 minute 13 seconds
NOTE: Scavenge failures indicate that a PICT header was found, but the header
was not valid. The file may contain a valid picture which this program could not
scavenge.
That’s all, folks.
To compile the Rez file use the following command line :
#5
Rez -t ZZZZ test.PICT.r -o 'test pictures'
FORMAT OF PICTURES IN A RESOURCE FILE
A PICT resource within a resource file has a specific format. All pictures begin
with a specific pattern of bytes which differ per picture version. I call this pattern the
Picture Header Pattern (PHP). Preceding this pattern exists an 8 byte rectangle which
represents the picture frame and a 2 byte integer which represents the picture byte
size. This size integer is actually the low order word for the picture’s true size.
Preceding the size integer in the file is a 4 byte longint value which contains the
physical size of the picture data. All pictures end with a pattern of bytes which I call
the Picture Tail Pattern (PTP). This pattern is the End-Of-Picture Opcode. For
version 1 pictures the pattern contains one byte, for version 2 it has two bytes.
Since a (non-QuickDraw) picture is worth a thousand words
+------------------+------------------+------------------+----------i
---+----------------------+--------------+
| PSize 4 | LSize 2 | Frame 8 | PHP X | Pict Data | PTP Y |
+------------------+------------------+------------------+----------i
---+----------------------+--------------+
For version 1 pictures, X = 2 and Y = 1
For version 2 pictures, X = 4 and Y = 2
PICTURE RESOURCE SEARCH ALGORITHM
The algorithm used to locate picture resources within a resource file is quite
straight forward. This algorithm contains 6 steps:
Step 1: Start at the beginning of the resource fork data
Step 2: Locate the next Picture Header Pattern
Step 3: Verify that the Picture Header Pattern is preceded by a valid rectangle
and the word and longword least significant word before the rectangle data
are equal
Step 4: Verify that the Picture Tail Pattern and the last opcode in the picture data
match
Step 5: If steps 2 to 4 are successful, then a picture has been found in the
resource file
Step 6: Repeat steps 2-5 until the physical end-of-file of the resource fork is
found
BIBLIOGRAPHY
Resource file format : Inside Macintosh, vol. I, p. 128+
QuickDraw pictures : Inside Macintosh, vol. I, p. 158+
QuickDraw picture opcodes: Apple Technical Note # 21, Inside Macintosh, vol. V,
p.92+
PICTURES IN TEST
id = 1000
id = 1001
id = 1002
id = 1003
id = 1004
Listing: PICTScavenger.make
# File: PICTScavenger.make
# Target: PICTScavenger
# Sources: PICTScavenger.p U_PICT_Scavenger.p
U_PICT_Scavenger.p.o PICTScavenger.make U_PICT_Scavenger.p
Pascal -ov -u U_PICT_Scavenger.p
PICTScavenger.p.o PICTScavenger.make PICTScavenger.p
Pascal -ov -u PICTScavenger.p
SOURCES = PICTScavenger.p U_PICT_Scavenger.p
OBJECTS = PICTScavenger.p.o U_PICT_Scavenger.p.o
Link -w -c 'MPS ' -t MPST ∂
{OBJECTS} ∂
"{Libraries}"stubs.o ∂
"{Libraries}"Runtime.o ∂
"{Libraries}"Interface.o ∂
"{PLibraries}"PasLib.o ∂
"{PLibraries}"SANELib.o ∂